Skip to main content

3.5 Software API and ROS

Kikobot C1 is controlled from your PC through Kikobot Studio or any custom application using a WebSocket JSON API on port 8080, backed by ROS 2 Humble packages under /opt/kikobot.

1. Starting the C1 software stack​

C1 uses the same motion stack and WebSocket bridge as C2; robot_profile in the handshake is "c1".

kikobot-backend c1
ModeCommand
Interactive + RVizkikobot-backend c1
Headlessexport KIKOBOT_HEADLESS=1 && kikobot-backend c1
systemdsudo systemctl start kikobot-backend@c1

Only one backend instance per robot model should run (lock file prevents duplicates).

Shipped documentation on the PC​

AssetPath
WebSocket guide (Markdown)/opt/kikobot/share/doc/WEBSOCKET_INTEGRATION_GUIDE.md
WebSocket guide (PDF)/opt/kikobot/share/doc/WEBSOCKET_INTEGRATION_GUIDE.pdf
Python example client/opt/kikobot/share/examples/kikobot_ws_client_example.py

2. WebSocket API (port 8080)​

3.1 Connection​

  • URL: ws://<host>:8080 (LAN) or ws://127.0.0.1:8080 (local)
  • Protocol: UTF-8 JSON, one object per message
  • Security: No authentication — use trusted network, VPN, or SSH tunnel only

3.2 Handshake (server → client)​

{
"type": "connected",
"message": "Connected to Kikobot C1 WebSocket Bridge",
"robot_profile": "c1",
"capabilities": {
"motion_planning_available": true,
"arc_booklet_available": true,
"hand_teaching_jog": true
}
}

3.3 Keep-alive​

{ "type": "ping", "timestamp": 1730000000 }

→ { "type": "pong", "timestamp": 1730000000 }

3.4 C1 bring-up sequence​

1. kikobot-backend c1
2. Connect WebSocket
3. { "type": "firmware_status" }
4. { "type": "start_firmware", "port": "/dev/ttyACM0" }
5. Listen for "joint_states" broadcasts
6. { "type": "home" } or motion commands

Firmware paths

C1_FIRMWARE_TYPEBehavior
python (default)Launches /opt/kikobot/share/c1/kikobot_c1_firmware_bridge.py
microrosLaunches micro-ROS agent; ESP must run c1_microros_firmware.ino

Override script: KIKOBOT_C1_FIRMWARE_SCRIPT in the backend environment.

Serial: Baud 1 000 000 for Python bridge (must match ESP sketch).

{ "type": "start_firmware", "port": "/dev/ttyACM0" }
{ "type": "stop_firmware" }
{ "type": "firmware_status" }

3. Command reference (summary)​

Angles are in degrees unless noted. See the full guide on disk for edge cases.

typePurpose
homeC1 home pose (firmware + planner sync)
jogSingle jog step (axis, direction, mode, step, speed)
hand_teachingTeach / save / gripper / firmware home (command array)
motion_planPlanned MoveJ / MoveL / Arc / Circle
start_firmware / stop_firmware / firmware_statusESP32 serial bridge
save_motor_poseRead joints from hardware
fk_requestForward kinematics
torque_release / torque_holdTorque off/on
hand_teach_points_recordEnable/disable teach point recording
set_do / get_diDigital I/O (bridge state)
start_waypoint_sequenceOptional arc/booklet automation
run_program / stop_programOptional Blockly-style runner

Jog example​

{
"type": "jog",
"axis": 0,
"direction": 1,
"mode": 0,
"step": 1.0,
"speed": 0.5
}

mode: 0 = joint, 1 = Cartesian. speed: 0.0–1.0.

Hand teaching (gripper / teach / home)​

{ "type": "hand_teaching", "command": [2.0, 0.0, 0.0] }
teachsaverunMeaning
100Teach mode on
010Save pose
200Open gripper
020Close gripper
300Home (firmware)

C1 home joint angles (degrees)​

Used by home and planner sync:

[-89.95, -29.52, -88.14, -29.76, 89.95, 89.95]

Joint names in telemetry match the C1 URDF (six revolute joints + gripper via hand teaching).


4. Motion planning (motion_plan)​

{
"type": "motion_plan",
"waypoints": [
{
"goal_joint_angles": [-89.95, -29.52, -88.14, -29.76, 89.95, 89.95],
"goal_ee_pose": [],
"motion_type": 0,
"speed_fraction": 0.35,
"sleep_time": 0
},
{
"goal_joint_angles": [-80.0, -25.0, -80.0, -25.0, 85.0, 85.0],
"goal_ee_pose": [],
"motion_type": 0,
"speed_fraction": 0.35,
"sleep_time": 0
}
]
}
motion_typeNameWaypoints per segment
0MoveJ2 (start joints, goal joints)
1MoveL2 (TCP pose: mm + deg)
2Arc3
3Circle3

Chaining A→B→C: use four waypoints with the middle pose duplicated on the segment boundary (same as Kikobot Studio).

Joint limits (degrees, planner): J1 ±165, J2 ±125, J3–J5 ±140, J6 ±175. Stay slightly inside limits (e.g. J2 ≤ 124.95°).

Success reply:

{ "type": "status", "status": "SUCCESS", "reason": "Motion planning completed successfully" }

5. Telemetry (server → all clients)​

typeContent
joint_statesjoint_names, angles (deg), angles_rad — ~30 Hz
jogging_feedbackDuring jog
motion_planning_feedbackDuring motion_plan; joint_angles in rad
statusCommand results / errors
motor_pose_saved, fk_resultPose / FK responses

Example:

{
"type": "joint_states",
"joint_names": ["Revolute 1", "Revolute 2", "Revolute 3", "Revolute 4", "Revolute 5", "Revolute 6"],
"angles": [-89.95, -29.52, -88.14, -29.76, 89.95, 89.95],
"angles_rad": [-1.57, -0.52, -1.54, -0.52, 1.57, 1.57]
}

6. Reference Python client​

pip install 'websockets>=12'
python3 /opt/kikobot/share/examples/kikobot_ws_client_example.py --host 127.0.0.1 status
python3 /opt/kikobot/share/examples/kikobot_ws_client_example.py --host <robot-ip> stream --seconds 10
python3 /opt/kikobot/share/examples/kikobot_ws_client_example.py --host 127.0.0.1 start-firmware --serial /dev/ttyACM0
python3 /opt/kikobot/share/examples/kikobot_ws_client_example.py --host 127.0.0.1 demo-movej

Use --host pointing at the machine where kikobot-backend c1 runs. For C1, pass the ESP serial device (often ttyACM0).


7. ROS 2 interface (advanced)​

The backend sources /opt/kikobot/ros/install/setup.bash. Integrators who add native ROS nodes must use the same ROS_DOMAIN_ID as the backend (default 0 if unset).

Typical packages (installed with backend)​

  • urdf_kikobot_description_v1_description — C1 URDF / visualization
  • kikobot_motion_planner — MoveJ/MoveL/Arc planning
  • custom_interfaces — services such as motor pose read

Launch entry​

kikobot-backend c1 internally runs the display launch, action servers, and bridge. For development from source, see repository start_c1_backend.sh (maintainers only).

Key ROS concepts​

ItemNotes
TrajectoriesFirmware bridge consumes trajectory points and forwards to ESP
/joint_statesPublished for visualization; firmware bridge polls motor pose
RVizStarted unless KIKOBOT_HEADLESS=1

8. ESP32 serial protocol (Python bridge)​

Host ↔ ESP32 framed binary protocol (CRC16-CCITT). Implemented in kikobot_c1_firmware_bridge.py and c1_serial_firmware.ino.

OpcodeDirectionPurpose
0x10 OP_TRAJ_POINTHost→MCUTrajectory point (6 joints + speed/accel)
0x11 OP_HAND_TEACHHost→MCUTeach / save / gripper / home
0x12 OP_REQ_HELLOHost→MCUFirmware version handshake
0x13 OP_SCAN_MOTORSHost→MCUScan servo IDs
0x14 OP_MOTOR_POSE_REQHost→MCURequest current positions
0x15 OP_TORQUE_CTRLHost→MCUTorque enable/disable
0x21 OP_HELLOMCU→HostJSON firmware info
0x23 OP_MOTOR_POSEMCU→HostJoint + gripper positions

J3/J4 may use sign conventions in firmware; the bridge aligns ROS degrees with servo degrees.


9. Kikobot Studio (UI)​

  • Application: kikobot-studio AppImage (version 1.0.0)
  • Robot selection: Choose C1 on the connection / robot page
  • Features: Jog, hand teaching, motion planning, optional camera page (with KIKOBOT_C1_CAMERA=1)
  • Studio and your WebSocket client can connect concurrently to port 8080

10. Troubleshooting (software)​

SymptomAction
Cannot connect to 8080Start kikobot-backend c1 or systemctl start kikobot-backend@c1
robot_profile is c2Wrong backend — restart with kikobot-backend c1
Firmware won’t startCheck port, baud 1M, ESP sketch flashed, /tmp/kikobot_firmware.log
context is invalid on motionRestart backend (stale ROS context)
websockets>=12 errorpip3 install --break-system-packages 'websockets>=12'
No camera on 8081export KIKOBOT_C1_CAMERA=1; install ros-humble-web-video-server
ss -ltn | grep 8080
tail -f /tmp/kikobot_websocket.log
tail -f /tmp/kikobot_c1_display.log

  • [Installation and Integration](/docs/Kikobot C1/3.4 Installation and Integration)
  • [FAQ and Downloads](/docs/Kikobot C1/3.6 FAQ and Downloads)
  • [Kikobot C2 software and API](/docs/Kikobot C2/4.2 Software API and ROS) (shared API; C2-specific firmware and home pose)